﻿using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

namespace QueryResource.Common
{
    /// <summary>
    /// 压缩类
    /// </summary>
    public static class DataCompression
    {
        /// <summary>
        /// 提供内部使用压缩字流的方法
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static byte[] ByteCompression(byte[] data, CompressionMode mode)
        {
            GZipStream zip = null;
            //DeflateStream zip = null;
            try
            {
                if (mode == CompressionMode.Compress)
                {
                    MemoryStream ms = new MemoryStream();
                    using (zip = new GZipStream(ms, mode, true))
                    {
                        zip.Write(data, 0, data.Length);
                    }
                    return ms.ToArray();
                }
                else
                {
                    MemoryStream ms = new MemoryStream();
                    ms.Write(data, 0, data.Length);
                    ms.Flush();
                    ms.Position = 0;
                    MemoryStream os = new MemoryStream();
                    using (zip = new GZipStream(ms, mode, true))
                    {

                        const int size = 1024;
                        byte[] buf = new byte[size];
                        int l;
                        do
                        {
                            l = zip.Read(buf, 0, size);
                            if (l == 0) l = zip.Read(buf, 0, size);
                            os.Write(buf, 0, l);
                        } while (l != 0);
                    }
                    return os.ToArray();
                }
            }
            catch
            {
                if (zip != null) zip.Close();
                return null;
            }
            finally
            {
                if (zip != null) zip.Close();
            }
        }

        public static byte[] SerializeData<T>(this T data) where T :class
        {
            using (MemoryStream memory = new MemoryStream())
            {
                
                BinaryFormatter formatter = new BinaryFormatter();

                formatter.Serialize(memory, data);
                return memory.ToArray();
            }
        }

        public static T DeserializeData<T>(this byte[] data) where T:class
        {
            if (data != null)
            {
                using (MemoryStream memeory = new MemoryStream(data))
                {
                    try
                    {//网络慢会引发异常
                        memeory.Position = 0;
                        memeory.Seek(0, SeekOrigin.Begin);
                        BinaryFormatter binary = new BinaryFormatter();
                        return (T)binary.Deserialize(memeory);
                    }
                    catch { return null; }
                }
            }
            return null;
        }

        public static void SerializeDataToFile<T>(this T data,string file,bool isXml) where T : class
        {
            using (FileStream fileStream = new FileStream(file, FileMode.Create))
            {
                if (isXml)
                {
                    XmlSerializer xml = new XmlSerializer(typeof(T));
                    xml.Serialize(fileStream, data);
                }
                else
                {
                    BinaryFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(fileStream, data);
                }
            }
        }

        public static T DeserializeDataToFile<T>(string file, bool isXml) where T : class
        {
            if (!File.Exists(file))
            {
                return null;
            }
            using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try
                {//网络慢会引发异常
                    fileStream.Position = 0;
                    fileStream.Seek(0, SeekOrigin.Begin);
                    if (isXml)
                    {
                        XmlSerializer xml = new XmlSerializer(typeof(T));
                        return (T)xml.Deserialize(fileStream);
                    }
                    BinaryFormatter binary = new BinaryFormatter();
                    return (T)binary.Deserialize(fileStream);
                }
                catch { return null; }
            }
        }
    }
}
